home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / sviluppo / svilupp2 / pike.lha / Pike-0.4.0 / master.pike next >
Text File  |  1997-01-10  |  8KB  |  347 lines

  1. string describe_backtrace(mixed *trace);
  2.  
  3. string pike_library_path;
  4.  
  5. mapping (string:string) environment=([]);
  6.  
  7. varargs mixed getenv(string s)
  8. {
  9.   if(!s) return environment;
  10.   return environment[s];
  11. }
  12.  
  13. void putenv(string var, string val)
  14. {
  15.   environment[var]=val;
  16. }
  17.  
  18. mapping (string:program) programs=([]);
  19.  
  20. /* This function is called whenever a module has built a clonable program
  21.  * with functions written in C and wants to notify the Pike part about
  22.  * this. It also supplies a suggested name for the program.
  23.  */
  24. void add_precompiled_program(string name, program p)
  25. {
  26.   programs[name]=p;
  27.  
  28.   if(sscanf(name,"/precompiled/%s",name))
  29.     add_constant(upper_case(name[..0])+name[1..],p);
  30. }
  31.  
  32. /* This function is called when the driver wants to cast a string
  33.  * to a program, this might be because of an explicit cast, an inherit
  34.  * or a implict cast. In the future it might receive more arguments,
  35.  * to aid the master finding the right program.
  36.  */
  37. program cast_to_program(string pname)
  38. {
  39.   if(pname[sizeof(pname)-3..sizeof(pname)]==".pike")
  40.     pname=pname[0..sizeof(pname)-4];
  41.  
  42.   function findprog=lambda(string pname)
  43.   {
  44.     program ret;
  45.  
  46.     if(ret=programs[pname]) return ret;
  47.   
  48.     if(file_stat(pname))
  49.     {
  50.       ret=compile_file(pname);
  51.     }
  52.     else if(file_stat(pname+".pike"))
  53.     {
  54.       ret=compile_file(pname+".pike");
  55.     }
  56. #if efun(ldopen)
  57.     else if(file_stat(pname+".so"))
  58.     {
  59.       ldopen(pname);
  60.       ret=programs[pname];
  61.     }
  62. #endif
  63.     if(ret) programs[pname]=ret;
  64.     return ret;
  65.   };
  66.  
  67.   if(pname[0]=='/')
  68.   {
  69.     return findprog(pname);
  70.   }else{
  71.     if(search(pname,"/")==-1)
  72.     {
  73.       string path;
  74.       if(string path=getenv("PIKE_INCLUDE_PATH"))
  75.       {
  76.     foreach(path/":", path)
  77.       if(program ret=findprog(combine_path(getcwd(),
  78.                            combine_path(path,pname))))
  79.          return ret;
  80.       }
  81.     }
  82.     return findprog(combine_path(getcwd(),pname));
  83.   }
  84. }
  85.  
  86. /* This function is called when an error occurs that is not caught
  87.  * with catch(). It's argument consists of:
  88.  * ({ error_string, backtrace }) where backtrace is the output from the
  89.  * backtrace() efun.
  90.  */
  91. void handle_error(mixed *trace)
  92. {
  93.   predef::trace(0);
  94.   werror(describe_backtrace(trace));
  95. }
  96.  
  97.  
  98.  
  99. object new(mixed prog, mixed ... args)
  100. {
  101.   return ((program)prog)(@args);
  102. }
  103.  
  104. /* Note that create is called before add_precompiled_program
  105.  */
  106. void create()
  107. {
  108.   /* make ourselves known */
  109.   add_constant("master",lambda() { return this_object(); });
  110.   add_constant("describe_backtrace",describe_backtrace);
  111.   add_constant("version",lambda() { return "Pike v0.4"; });
  112.   add_constant("mkmultiset",lambda(mixed *a) { return aggregate_multiset(@a); });
  113.   add_constant("strlen",sizeof);
  114.   add_constant("new",new);
  115.   add_constant("clone",new);
  116.  
  117.   random_seed(time() + (getpid() * 0x11111111));
  118. }
  119.  
  120. /*
  121.  * This function is called whenever a inherit is called for.
  122.  * It is supposed to return the program to inherit.
  123.  * The first argument is the argument given to inherit, and the second
  124.  * is the file name of the program currently compiling. Note that the
  125.  * file name can be changed with #line, or set by compile_string, so
  126.  * it can not be 100% trusted to be a filename.
  127.  * previous_object(), can be virtually anything in this function, as it
  128.  * is called from the compiler.
  129.  */
  130. program handle_inherit(string pname, string current_file)
  131. {
  132.   program p;
  133.   string *tmp;
  134.   p=cast_to_program(pname);
  135.   if(p) return p;
  136.   tmp=current_file/"/";
  137.   tmp[-1]=pname;
  138.   return cast_to_program(tmp*"/");
  139. }
  140.  
  141. mapping (string:object) objects=(["/master.pike":this_object()]);
  142.  
  143. /* This function is called when the drivers wants to cast a string
  144.  * to an object because of an implict or explicit cast. This function
  145.  * may also receive more arguments in the future.
  146.  */
  147. object cast_to_object(string oname)
  148. {
  149.   object ret;
  150.  
  151.   if(oname[0]!='/')
  152.     oname=combine_path(getcwd(),oname);
  153.  
  154.   if(oname[sizeof(oname)-3..sizeof(oname)]==".pike")
  155.     oname=oname[0..sizeof(oname)-4];
  156.  
  157.   if(ret=objects[oname]) return ret;
  158.  
  159.   return objects[oname]=cast_to_program(oname)();
  160. }
  161.  
  162.  
  163. /* This function is called when all the driver is done with all setup
  164.  * of modules, efuns, tables etc. etc. and is ready to start executing
  165.  * _real_ programs. It receives the arguments not meant for the driver
  166.  * and an array containing the environment variables on the same form as
  167.  * a C program receives them.
  168.  */
  169. void _main(string *argv, string *env)
  170. {
  171.   int i;
  172.   object script;
  173.   string a,b;
  174.   string *q;
  175.  
  176.   foreach(env,a) if(sscanf(a,"%s=%s",a,b)) environment[a]=b;
  177.   add_constant("getenv",getenv);
  178.   add_constant("putenv",putenv);
  179.  
  180.   add_constant("write",cast_to_program("/precompiled/file")("stdout")->write);
  181.  
  182.   a=backtrace()[-1][0];
  183.   q=a/"/";
  184.   pike_library_path = q[0..sizeof(q)-2] * "/";
  185.  
  186. //  clone(compile_file(pike_library_path+"/simulate.pike"));
  187.  
  188.   if(!sizeof(argv))
  189.   {
  190.     werror("Usage: pike [-driver options] script [script arguments]\n");
  191.     exit(1);
  192.   }
  193.   script=(object)argv[0];
  194.  
  195.   if(!script->main)
  196.   {
  197.     werror("Error: "+argv[0]+" has no main().\n");
  198.     exit(1);
  199.   }
  200.  
  201.   i=script->main(sizeof(argv),argv,env);
  202.   if(i >=0) exit(i);
  203. }
  204.  
  205. mixed inhibit_compile_errors;
  206.  
  207. void set_inhibit_compile_errors(mixed f)
  208. {
  209.   inhibit_compile_errors=f;
  210. }
  211.  
  212. string trim_file_name(string s)
  213. {
  214.   if(getenv("SHORT_PIKE_ERRORS"))
  215.     return (s/"/")[-1];
  216.   return s;
  217. }
  218.  
  219. /*
  220.  * This function is called whenever a compiling error occurs,
  221.  * Nothing strange about it.
  222.  * Note that previous_object cannot be trusted in ths function, because
  223.  * the compiler calls this function.
  224.  */
  225. void compile_error(string file,int line,string err)
  226. {
  227.   if(!inhibit_compile_errors)
  228.   {
  229.     werror(sprintf("%s:%d:%s\n",trim_file_name(file),line,err));
  230.   }
  231.   else if(functionp(inhibit_compile_errors))
  232.   {
  233.     inhibit_compile_errors(file,line,err);
  234.   }
  235. }
  236.  
  237. /* This function is called whenever an #include directive is encountered
  238.  * it receives the argument for #include and should return the file name
  239.  * of the file to include
  240.  * Note that previous_object cannot be trusted in ths function, because
  241.  * the compiler calls this function.
  242.  */
  243. string handle_include(string f,
  244.               string current_file,
  245.               int local_include)
  246. {
  247.   string *tmp, path;
  248.  
  249.   if(local_include)
  250.   {
  251.     tmp=current_file/"/";
  252.     tmp[-1]=f;
  253.     path=combine_path(getcwd(),tmp*"/");
  254.     if(!file_stat(path)) return 0;
  255.   }
  256.   else
  257.   {
  258.     if(path=getenv("PIKE_INCLUDE_PATH"))
  259.     {
  260.       foreach(path/":", path)
  261.       {
  262.     path=combine_path(path,f);
  263.     if(file_stat(path))
  264.       break;
  265.     else
  266.       path=0;
  267.       }
  268.     }
  269.     
  270.     if(!path)
  271.     {
  272.       path=combine_path(pike_library_path+"/include",f);
  273.       if(!file_stat(path)) path=0;
  274.     }
  275.   }
  276.  
  277.   if(path)
  278.   {
  279.     /* Handle preload */
  280.  
  281.     if(path[-1]=='h' && path[-2]=='.' &&
  282.        file_stat(path[0..sizeof(path)-2]+"pre.pike"))
  283.     {
  284.       cast_to_object(path[0..sizeof(path)-2]+"pre.pike");
  285.     }
  286.   }
  287.  
  288.   return path;
  289. }
  290.  
  291. /* It is possible that this should be a real efun,
  292.  * it is currently used by handle_error to convert a backtrace to a
  293.  * readable message.
  294.  */
  295. string describe_backtrace(mixed *trace)
  296. {
  297.   int e;
  298.   string ret;
  299.  
  300.   if(arrayp(trace) && sizeof(trace)==2 && stringp(trace[0]))
  301.   {
  302.     ret=trace[0];
  303.     trace=trace[1];
  304.   }else{
  305.     ret="";
  306.   }
  307.  
  308.   if(!arrayp(trace))
  309.   {
  310.     ret+="No backtrace.\n";
  311.   }else{
  312.     for(e=sizeof(trace)-1;e>=0;e--)
  313.     {
  314.       mixed tmp;
  315.       string row;
  316.  
  317.       tmp=trace[e];
  318.       if(stringp(tmp))
  319.       {
  320.     row=tmp;
  321.       }
  322.       else if(arrayp(tmp))
  323.       {
  324.     row="";
  325.     if(sizeof(tmp)>=3 && functionp(tmp[2]))
  326.     {
  327.       row=function_name(tmp[2])+" in ";
  328.     }
  329.  
  330.     if(sizeof(tmp)>=2 && stringp(tmp[0]) && intp(tmp[1]))
  331.     {
  332.       row+="line "+tmp[1]+" in "+trim_file_name(tmp[0]);
  333.     }else{
  334.       row+="Unknown program";
  335.     }
  336.       }
  337.       else
  338.       {
  339.     row="Destructed object";
  340.       }
  341.       ret+=row+"\n";
  342.     }
  343.   }
  344.  
  345.   return ret;
  346. }
  347.